package cn.duhengkui.national.valuelist.gen.mysql;

import java.io.File;
import java.sql.Types;

import cn.duhengkui.national.valuelist.gen.CreateUtil;
import cn.duhengkui.national.valuelist.gen.DataBaseInfo;
import cn.duhengkui.national.valuelist.gen.EntityFactory;
import cn.duhengkui.national.valuelist.tool.Column;
import cn.duhengkui.national.valuelist.tool.EntityData;

/**
 * entity工厂实现(mysql)
 * @author duhengkui
 *
 */
public class EntityFactoryImpl implements EntityFactory{

	@Override
	public void createEntityFile(String packageName, String sourcePath, EntityData entity, DataBaseInfo dataBaseInfo) {
		String line = System.lineSeparator();//System.getProperty("line.separator");
		String tab = "\t";
		StringBuffer code = new StringBuffer();
		code.append("package ").append(packageName).append(";").append(line).append(line);
		//code.append("import java.sql.JDBCType;").append(line);
		code.append("import cn.duhengkui.national.valuelist.core.entity.BaseEntity;").append(line);
		code.append("import cn.duhengkui.national.valuelist.annotation.Entity;").append(line);
		code.append("import cn.duhengkui.national.valuelist.annotation.EntityType;").append(line);
		code.append("import cn.duhengkui.national.valuelist.annotation.Column;").append(line).append(line);
		code.append("@Entity(name=\"").append(entity.getName()).append("\", type=EntityType.").append(entity.getType()).append(")").append(line);
		code.append("public class ").append(CreateUtil.className(entity.getName())).append(" extends ").append("BaseEntity {").append(line).append(line);
		StringBuffer fields = new StringBuffer();
		StringBuffer methods = new StringBuffer();
		StringBuffer hashCode = new StringBuffer();
		StringBuffer equals = new StringBuffer();
		hashCode.append(tab).append("public int hashCode() {").append(line)
		.append(tab).append(tab).append("final int prime = 31;").append(line)
		.append(tab).append(tab).append("int result = 1;").append(line);
		equals.append(tab).append("public boolean equals(Object obj) {").append(line)
		.append(tab).append(tab).append("if (this == obj)").append(line)
		.append(tab).append(tab).append(tab).append("return true;").append(line)
		.append(tab).append(tab).append("if (obj == null)").append(line)
		.append(tab).append(tab).append(tab).append("return false;").append(line)
		.append(tab).append(tab).append("if (getClass() != obj.getClass())").append(line)
		.append(tab).append(tab).append(tab).append("return false;").append(line)
		.append(tab).append(tab).append(CreateUtil.className(entity.getName())).append(" other = (").append(CreateUtil.className(entity.getName())).append(") obj;").append(line);
		for(Column column : entity.getColumnList()) {
			fields.append(tab).append("@Column(name=\"").append(column.getName()).append("\", isPK=").append(column.isPK()).append(", isNotNull=")
			.append(column.isNotNull()).append(", length=").append(column.getLength()).append(", precision=").append(column.getPrecision())
			.append(", scale=").append(column.getScale())
			//.append(", jdbcType=").append(getJDBCType(column))
			.append(")").append(line);
			fields.append(tab).append("private ").append(getStringType(column, true)).append(" ")
			.append(CreateUtil.fieldName(column.getName())).append(CreateUtil.defaultValue(column.getType(), column.getDefaultValue())).append(";").append(line).append(line);
			
			methods.append(tab).append("public ").append(getStringType(column, true)).append(" ").append(CreateUtil.getterName(column.getName()))
			.append("() {").append(line).append(tab).append(tab).append("return ").append(CreateUtil.fieldName(column.getName())).append(";").append(line).append(tab)
			.append("}").append(line);
			methods.append(tab).append("public void ").append(CreateUtil.setterName(column.getName())).append("(").append(getStringType(column,true))
			.append(" ").append(CreateUtil.fieldName(column.getName())).append(") {").append(line).append(tab).append(tab).append("this.")
			.append(CreateUtil.fieldName(column.getName())).append(" = ").append(CreateUtil.fieldName(column.getName())).append(";").append(line).append(tab).append("}")
			.append(line);
			
			if (column.isPK()) {
				hashCode.append(tab).append(tab).append("result = prime * result + ((").append(CreateUtil.fieldName(column.getName()))
				.append(" == null) ? 0 : ").append(CreateUtil.fieldName(column.getName())).append(".hashCode());").append(line);
				
				equals.append(tab).append(tab).append("if (").append(CreateUtil.fieldName(column.getName())).append(" == null) {").append(line)
				.append(tab).append(tab).append(tab).append("if (other.").append(CreateUtil.fieldName(column.getName())).append(" != null)").append(line)
				.append(tab).append(tab).append(tab).append(tab).append("return false;").append(line)
				.append(tab).append(tab).append("} else if (!").append(CreateUtil.fieldName(column.getName())).append(".equals(other.")
				.append(CreateUtil.fieldName(column.getName())).append(")) {").append(line)
				.append(tab).append(tab).append(tab).append("return false;").append(line).append(tab).append(tab).append("}").append(line);
			}
		}
		hashCode.append(tab).append(tab).append("return result;").append(line).append(tab).append("}").append(line);
		equals.append(tab).append(tab).append("return true;").append(line).append(tab).append("}").append(line);
		code.append(fields.toString());
		code.append(methods.toString());
		if ("TABLE".equals(entity.getType())) {
			code.append(hashCode.toString());
			code.append(equals.toString());
		}
		code.append("}");
		String path = System.getProperty("user.dir") + File.separator + sourcePath.replace("/", File.separator) + File.separator 
		+ packageName.replace(".", File.separator);
		CreateUtil.writeFile(path, CreateUtil.className(entity.getName()) + ".java", code);
		
	}


	@Override
	public String getStringType(Column column, boolean isExtentObject) {
		switch (column.getType()) {
		case Types.CHAR:
		case Types.NCHAR:
		case Types.LONGVARCHAR:
		case Types.LONGNVARCHAR:
		case Types.VARCHAR:
		case Types.NVARCHAR:
			 return "java.lang.String";
		case Types.BIT:
			return "java.lang.Boolean";
		case Types.NUMERIC:
		case Types.DECIMAL:
			return "java.math.BigDecimal";
		case Types.BOOLEAN:
			return "java.lang.Boolean";	
		case Types.TINYINT:
		case Types.SMALLINT:
		case Types.INTEGER:
			return "java.lang.Integer";
		case Types.BIGINT:
			return "java.lang.Long";
		case Types.REAL:
			return "java.lang.Float";
		case Types.FLOAT:
		case Types.DOUBLE:
				return "java.lang.Double";
		case Types.BINARY:
		case Types.VARBINARY:
		case Types.LONGVARBINARY:
			return "byte[]";
		case Types.DATE:
			return "java.sql.Date";
		case Types.TIME:
			return "java.sql.Time";
		case Types.TIMESTAMP:
			return "java.sql.Timestamp";
		default:
			return "java.lang.Object";
			
		}
	}
	

}
